package com.lujieni.springbootsecurity.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.lujieni.springbootsecurity.dao.RoleMapper;
import com.lujieni.springbootsecurity.dao.UserRoleMapper;
import com.lujieni.springbootsecurity.po.RoleDO;
import com.lujieni.springbootsecurity.po.UserRoleDO;
import com.lujieni.springbootsecurity.utils.CollectionUtils;
import com.lujieni.springbootsecurity.utils.SecurityFrameworkUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @Author：小鹿爱吃鱼
 * @Date: 2025/5/30 16:03
 * @Description:
 */
public class PermissonService {

    private static final int timeOut = 10 * 60;

    private static final int cacheMaximumSize = 500;

    private final LoadingCache<KeyValue<Long, List<String>>, Boolean> hasAnyRolesCache = CacheBuilder.newBuilder()
            .maximumSize(cacheMaximumSize)
            //
            .refreshAfterWrite(timeOut, TimeUnit.SECONDS)
            .build(new CacheLoader<KeyValue<Long, List<String>>, Boolean>() {
                // 缓存中获取不到值会回调这里
                @Override
                public Boolean load(KeyValue<Long, List<String>> key) throws Exception {
                    return checkIsContainRole(key.key, key.value);
                }
            });


    private boolean checkIsContainRole(Long userId, List<String> roleCodeList){
        if(CollectionUtil.isEmpty(roleCodeList) || userId == null){
            return false;
        }
        List<UserRoleDO> userRoleList = SpringUtil.getBean(UserRoleMapper.class).selectList(new LambdaQueryWrapper<UserRoleDO>().eq(UserRoleDO::getUserId, userId));
        List<Long> roleIdList = CollectionUtils.convertList(userRoleList, UserRoleDO::getRoleId);
        if(CollectionUtil.isEmpty(roleIdList)){
            return false;
        }
        List<RoleDO> roleDOList = SpringUtil.getBean(RoleMapper.class).selectByIds(roleIdList);
        if(CollectionUtil.isEmpty(roleDOList)){
            return false;
        }
        for (String roleCode : roleCodeList) {
            if(roleDOList.stream().map(RoleDO::getCode).anyMatch(e-> Objects.equals(roleCode, e))){
                return true;
            }
        }
        return false;
    }

    public boolean hasAnyRoles(String... roles) throws ExecutionException {
        // 权限校验
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        if (userId == null) {
            return false;
        }
        return hasAnyRolesCache.get(new KeyValue<>(userId, Arrays.asList(roles)));
    }


    /**
     * Key Value 的键值对
     *
     * @author 芋道源码
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    private static class KeyValue<K, V>{
        private K key;
        private V value;
    }

}
